<template>
  <div v-show="visible">

    <GxToolbar style="margin-bottom: 13px" class="c-btn">
      <template #left>
        <SearchForm :data="formData" class="c-search-form" @search="search">
          <el-row>
            <el-form-item label="选择日志仓">
              <el-select v-model="formData.storage" clearable filterable placeholder="请选择" style="width:420px;"
                @clear="reGetStorageOptions">
                <el-option v-for="item in storageOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
            <el-form-item label="系统名">
              <el-select v-model="formData.system" :multiple="false" filterable allow-create default-first-option
                style="width:420px;" clearable :reserve-keyword="false" placeholder="请输入系统名">
                <el-option v-for="item in systemOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
            <el-form-item label="日志级别">
              <el-select v-model="formData.loglevel" multiple clearable :reserve-keyword="true" style="width:420px;"
                placeholder="请选择...">
                <el-option label="ERROR" value="error" />
                <el-option label="WARN" value="warn" />
                <el-option label="INFO" value="info" />
                <el-option label="DEBUG" value="debug" />
              </el-select>
            </el-form-item>
            <el-form-item label="时间范围">
              <el-date-picker v-model="formData.datetime" type="datetimerange" :shortcuts="shortcuts" range-separator="～"
                value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始时间" end-placeholder="结束时间"
                popper-class="c-datapicker" />
            </el-form-item>
            <el-form-item label="用户">
              <el-input v-model="formData.user" placeholder="请输入用户" maxlength="100" style="width:420px;"
                @keyup.enter="() => $emitter.emit('fnSearch')" />
            </el-form-item>
          </el-row>
        </SearchForm>
      </template>

      <template #right>
        <el-tooltip v-if="showTestBtn" content="生成测试数据" placement="top">
          <el-button circle @click="genTestData">
            <SvgIcon name="quick" />
          </el-button>
        </el-tooltip>
        <el-tooltip :content="autoSearchMode ? '停止自动查询' : '开始自动查询'" placement="top">
          <el-button circle @click="switchAutoSearchMode">
            <SvgIcon v-if="!autoSearchMode" name="play" />
            <SvgIcon v-if="autoSearchMode" name="stop" />
          </el-button>
        </el-tooltip>
        <el-tooltip content="缩放" placement="top">
          <el-button circle @click="emitter.emit('main:switchMaximizePage')">
            <SvgIcon name="zoom" />
          </el-button>
        </el-tooltip>
        <el-tooltip content="下载当前检索结果" placement="top">
          <el-button circle @click="fnDownload">
            <SvgIcon name="download" />
          </el-button>
        </el-tooltip>
        <GxPageTableConfig :tid="tid" :page-config="pageSettingStore" />
      </template>
    </GxToolbar>

    <GxTable ref="table" v-loading="showTableLoadding" scrollbar-always-on :enable-header-contextmenu="false"
      :enable-first-expand="true" stripe :tid="tid" :data="tableData" :height="tableHeight" class="c-gx-table c-glc-table"
      row-key="id">
    </GxTable>

    <div>
      <div style="display:flex;justify-content:space-between;">
        <div style="min-height:30px;padding-top:5px; line-height:30px; color: #909399;" v-text="info"></div>
      </div>
    </div>

  </div>
</template>

<script setup>
import { useEmitter, $emitter, usePageMainHooks, useTabsState } from "~/pkgs";
import { userLogout, enableLogin } from "~/api";

const tabsState = useTabsState();
const emitter = useEmitter(tabsState.activePath);
const router = useRouter();

const opt = {
  emitter,
  withoutSearchForm: true,
};
const { formData, visible, tableData, tableHeight, pageSettingStore, showTableLoadding } = usePageMainHooks(opt);

const showTestBtn = ref(false); // 是否显示生成测试数据按钮
const autoSearchMode = ref(false); // 自动查询
const table = ref(); // 表格实例
const tid = ref('searchMain231126'); // 表格ID
const info = ref(''); // 底部提示信息
const storageOptions = ref([]) // 日志仓
const systemSet = new Set();
const systemOptions = ref([]) // 系统名
const lastStoreName = ref('') // 检索结果中最久远的一条日志所属的日志仓名称
const maxMatchCount = ref('0') // 最大匹配件数(字符串)
const moreConditon = ref(null)
const shortcuts = ref([
  {
    text: '近5分钟',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 5 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近10分钟',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 10 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近15分钟',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 15 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近20分钟',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 20 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近30分钟',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 30 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近1小时',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 60 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近2小时',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 2 * 60 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近3小时',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 3 * 60 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
  {
    text: '近4小时',
    value: () => {
      const start = new Date()
      start.setTime(start.getTime() - 4 * 60 * 60 * 1000)
      const end = new Date()
      return [start, end]
    },
  },
]);

// 初期默认检索
onMounted(async () => {
  const configStore = $emitter.emit('$table:config', { id: tid.value });
  !configStore.columns.length && $emitter.emit('$table:config', { id: tid.value, update: true }); // 首次使用开启默认布局
  // 日志仓列表查询
  const url = `/v1/store/names`;
  $post(url, {}, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    console.log(rs)
    if (rs.success) {
      const names = rs.result || [];
      for (let i = 0; i < names.length; i++) {
        storageOptions.value.push({ value: names[i], label: `日志仓：${names[i]}` })
      }
      if (names[0]) {
        $emitter.emit("defaultStorageCondtion", names[0]); // 小蓝点提示判断用
        formData.value.storage = names[0]; // 选中第一个日志仓作为默认条件
      }

      // 默认检索（查取好日志仓后再做检索）
      search();

    } else if (rs.code == 403) {
      userLogout(); // 403 时登出
      router.push('/login');
    }
  });

  // 查询有权限的系统名
  $post('/v1/store/systems', {}, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    if (rs.success && rs.result?.length) {
      for (let i = 0; i < rs.result.length; i++) {
        systemSet.add(rs.result[i]);
        systemSet.add(rs.result[i]) && systemOptions.value.push({ value: rs.result[i], label: rs.result[i] });
      }
    }
  });

  // 查询是否测试模式
  $post('/v1/store/mode', {}, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    showTestBtn.value = rs.success && rs.result
  });

  // 滚动底部触发检索更多
  const scrollWrap = document.querySelector('.c-glc-table .el-scrollbar__wrap')
  scrollWrap.addEventListener('scroll', (e) => {
    // e.target.scrollTop 为0时是滚动到顶部，不触发自动加载前一页数据，重新检索吧
    const scrollDistance = e.target.scrollHeight - e.target.scrollTop - e.target.clientHeight
    if (scrollDistance <= 0) {
      searchMore(); // 滚动到了底部，自动加载后一页
    }
  });

  // 检查下，避免不需要登录又还显示着登录状态
  await enableLogin();
});

// 清除日志仓条件时，重新拉取最新日志仓列表
function reGetStorageOptions() {
  const url = `/v1/store/names`;
  $post(url, {}, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    console.log(rs)
    if (rs.success) {
      const names = rs.result || [];
      if (names.length) {
        storageOptions.value.splice(0, storageOptions.value.length)
        for (let i = 0; i < names.length; i++) {
          storageOptions.value.push({ value: names[i], label: `日志仓：${names[i]}` })
        }
      }
      if (names[0]) {
        $emitter.emit("defaultStorageCondtion", names[0]); // 小蓝点提示判断用
      }
    }
  });
}

// 生成测试数据
function genTestData() {
  $post('/v1/log/addTestData', {}, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    $msg.info(rs.message);
  });
}

function isAutoSearchMode() {
  return autoSearchMode.value
}
function switchAutoSearchMode(changMode = true) {
  changMode && (autoSearchMode.value = !autoSearchMode.value);
  if (autoSearchMode.value) {
    search();
    setTimeout(() => {
      isAutoSearchMode() && switchAutoSearchMode(false);
    }, 5000);
  }
}

function search() {
  autoSearchMode.value ? (showTableLoadding.value = false) : (showTableLoadding.value = true);
  const url = `/v1/log/search`;

  // 检索条件
  const data = {};
  data.searchKey = formData.value.searchKeys;
  data.storeName = formData.value.storage;
  data.system = formData.value.system;
  data.loglevel = (formData.value.loglevel || []).join(',');
  data.datetimeFrom = (formData.value.datetime || ['', ''])[0];
  data.datetimeTo = (formData.value.datetime || ['', ''])[1];
  data.user = formData.value.user;

  // 保存好滚动检索的输入条件，保持和检索时一致，避免修改输入再滚动查询而出现矛盾结果
  moreConditon.value = data;

  $post(url, data, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    console.log(rs)
    if (rs.success) {
      const resultData = rs.result.data || [];
      const pagesize = rs.result.pagesize - 0;
      tableData.value.splice(0, tableData.value.length);  // 删除原全部元素，nextTick时再插入新查询结果
      document.querySelector('.c-glc-table .el-scrollbar__wrap').scrollTop = 0; // 滚动到顶部
      rs.result.laststorename && (lastStoreName.value = rs.result.laststorename); // 查到有结果时，更新
      maxMatchCount.value = rs.result.count; // 最大匹配件数

      nextTick(() => {
        resultData.forEach(item => {
          tableData.value.push(item);
          item.system && !systemSet.has(item.system) && systemSet.add(item.system) && systemOptions.value.push({ value: item.system, label: item.system });
        });

        if (resultData.length < pagesize) {
          info.value = `日志总量 ${rs.result.total} 条，当前条件最多匹配 ${tableData.value.length} 条，正展示前 ${tableData.value.length} 条，查询${rs.result.timemessage}`
        } else {
          info.value = `日志总量 ${rs.result.total} 条，当前条件最多匹配 ${maxMatchCount.value} 条，正展示前 ${tableData.value.length} 条，查询${rs.result.timemessage}`
        }
      });

    } else if (rs.code == 403) {
      userLogout(); // 403 时登出
      router.push('/login');
    }
  }).finally(() => {
    showTableLoadding.value = false;
  });
}

function searchMore() {
  if (tableData.value.length >= 5000) {
    if (info.value.indexOf('请考虑') < 0) {
      info.value += ` （数据太多不再自动加载，请考虑添加条件）`
    }
    return
  }

  const url = `/v1/log/search`;
  moreConditon.value.forward = true
  moreConditon.value.currentId = tableData.value[tableData.value.length - 1].id; // 相对最后条id，继续找后面的日志
  moreConditon.value.currentStoreName = lastStoreName.value;  // 相对最后条id的所属日志仓

  $post(url, moreConditon.value, null, { 'Content-Type': 'application/x-www-form-urlencoded' }).then(rs => {
    console.log(rs)
    if (rs.success) {
      const resultData = rs.result.data || [];
      const pagesize = rs.result.pagesize - 0;
      tableData.value.push(...resultData)
      rs.result.laststorename && (lastStoreName.value = rs.result.laststorename); // 查到有结果时，更新

      if (resultData.length < pagesize) {
        info.value = `日志总量 ${rs.result.total} 条，当前条件最多匹配 ${tableData.value.length} 条，正展示前 ${tableData.value.length} 条，查询${rs.result.timemessage}`
      } else {
        (rs.result.count - 0 < maxMatchCount.value - 0) && (maxMatchCount.value = rs.result.count) // 控制maxMatchCount只会更小以减少误差
        info.value = `日志总量 ${rs.result.total} 条，当前条件最多匹配 ${maxMatchCount.value} 条，正展示前 ${tableData.value.length} 条，查询${rs.result.timemessage}`
      }

      nextTick(() => {
        resultData.forEach(item => {
          item.system && !systemSet.has(item.system) && systemSet.add(item.system) && systemOptions.value.push({ value: item.system, label: item.system });
        });
      });
    } else if (rs.code == 403) {
      userLogout(); // 403 时登出
    }
  })
}

// 下载当前检索结果
function fnDownload() {
  let fileContent = '';
  const tableConfigStore = $emitter.emit('$table:config', { id: tid.value })
  tableData.value.forEach(item => {
    let flg = false;
    tableConfigStore.columns.forEach(oCol => {
      if (!oCol.hidden && !oCol.editType.startsWith('$') && oCol.editType != 'text') {
        flg && (fileContent += ',');
        fileContent += item[oCol.field];
        flg = true;
      }
    })
    fileContent += ',';
    fileContent += (item.detail || item.text);
    fileContent += '\r\n';
  })

  const blob = new Blob([fileContent], { type: 'text/plain' });  // 创建Blob对象
  const downloadLink = document.createElement('a');
  downloadLink.href = URL.createObjectURL(blob);
  downloadLink.download = 'logfile.txt'; // 文件名
  downloadLink.click(); // 模拟点击下载链接
}
</script>

<style>
.c-glc-table .el-popper.is-dark {
  display: none;
}

.x-detail {
  padding: 5px 5px 5px 30px;
  background-color: floralwhite;
}

.c-search-form .c-search-form-item {
  margin-bottom: 0;
}

.c-search-form .c-btn-badge.el-badge .el-button--small.is-circle {
  /* width: var(--el-button-size);
  min-width: var(--el-button-size); */
  width: 30px;
  min-width: 30px;
  height: 30px;
  min-height: 30px;
  margin-top: -3px;
}

.c-search-form.el-form--inline .el-input {
  --el-input-width: 100%;
}

.c-search-form .el-form-item--small .el-form-item__label {
  height: 30px;
  line-height: 30px;
}

.c-datapicker.el-popper.is-pure {
  margin-left: -100px;
}
</style>
